<?php


namespace App\Service;


use App\Constants\ErrorCode;
use App\Exception\BusinessException;
use App\Model\data\CurrentShopData;
use App\Model\LinkIndustry;
use Hyperf\DbConnection\Db;
use Hyperf\Di\Annotation\Inject;
use Hyperf\Utils\ApplicationContext;
use Swoole\NameResolver\Redis;

abstract class BaseService
{

    /**
     *@inject
     * @var QueueService
     */
    private $queueService;
    /**
     * GetModelInstance
     * 获取模型类实例
     * @return mixed
     */
    protected function getModelInstance()
    {
        $key = static::class;
        $key = substr($key, strripos($key, '\\') + 1);
        if (substr($key, -7) == 'Service') {
            $key = ucfirst(substr($key, 0, strlen($key) - 7));
            $fileName = BASE_PATH . "/app/Model/{$key}.php";
            $className = "App\\Model\\{$key}";
            if (file_exists($fileName)) {
                return make($className);
            }
        }
        throw new \RuntimeException("模型{$key}不存在，文件不存在！", ErrorCode::SERVER_ERROR);
    }

//    redis存取
    public function redis_set($ticket_index,$params,$times=86400*30){
        $container = ApplicationContext::getContainer();
        $redis = $container->get(\Hyperf\Redis\Redis::class);
        var_dump($params);
       return $redis->set($ticket_index, json_encode($params),$times);
    }

    public function redis_get($ticket_index){
        $container = ApplicationContext::getContainer();
        $redis = $container->get(\Hyperf\Redis\Redis::class);
        return  json_decode($redis->get($ticket_index),true);
    }



//    todo redis搜索  未完成
    public function redis_scan($ticket_index,$value){
        $container = ApplicationContext::getContainer();
        $redis = $container->get(\Hyperf\Redis\Redis::class);
        return  $redis->hScan($ticket_index,$value,$value);
    }

    //    redis队列
    public function redis_push($ticket_index,$params,$sort='left',$times=86400*30){
        $container = ApplicationContext::getContainer();
        $redis = $container->get(\Hyperf\Redis\Redis::class);
        if($sort=='left'){
            return $redis->lPush($ticket_index, json_encode($params),$times);
        }else{
            return $redis->rPush($ticket_index, json_encode($params),$times);
        }
    }
    //    redis存取
    public function redis_pop($ticket_index,$sort='left'){
        $container = ApplicationContext::getContainer();
        $redis = $container->get(\Hyperf\Redis\Redis::class);
        $redis->sAdd('2','2');
        if($sort=='left'){
            return $redis->lPop($ticket_index);
        }else{
            return $redis->rPop($ticket_index);
        }
    }

    public function ws_redis_retrieve(int $fd,int $link_id){
        $ttl = 3600;
        $container = ApplicationContext::getContainer();
        $redis = $container->get(\Hyperf\Redis\Redis::class);
        //获取所有的客户端id
        $fdList = $redis->sMembers('websocket_fds');
        //如果当前客户端在客户端集合中,就刷新
        if (in_array($fd, $fdList)) {
            $key = 'fd_user_'.$link_id;
            var_dump($key);
            $res1 = $redis->sAdd('websocket_fds', $fd);
            $redis->expire('websocket_fds', $ttl);
            if($redis->get($key)){
                $redis->expire($key,$ttl);
            }else{
                $redis->set($key,$fd,$ttl);
            }
        }
    }

    public function ws_redis_add(int $fd,int $link_id){
        //保存客户端id
        $ttl = 3600;
        $container = ApplicationContext::getContainer();
        $redis = $container->get(\Hyperf\Redis\Redis::class);
        $redis->sAdd('websocket_fds',$fd);
        $redis->expire('websocket_fds', $ttl);

        $key = 'fd_user_'.$link_id;
        if($redis->get($key)){
            $redis->expire($key,$ttl);
        }else{
            $redis->set($key,$fd,$ttl);
        }
    }

    public function ws_redis_del(int $fd,int $link_id){
        //保存客户端id
        $container = ApplicationContext::getContainer();
        $redis = $container->get(\Hyperf\Redis\Redis::class);
        //移除集合中指定的value
        $res1 = $redis->sRem('websocket_fds', $fd);
        $key = 'fd_user_'.$link_id;
        $redis->del($key);
        var_dump('ws_redis_del:'.$fd);
        var_dump('$link_id:'.$link_id);
        var_dump($res1);
    }

    //一般操作的修改展示状态
    public function change_show(array $ids, bool $is_show, $admin_id)
    {
        $instance = $this->getModelInstance();
        return $instance->whereIn('id', $ids)->update([
            'is_show' => $is_show,
            'update_by' => $admin_id,
            'updated_at' => date('Y-m-d H:i:s'),
        ]);
    }

    //一般操作的修改es同步
    public function es_push($product_id,$type)
    {
        $data = ['product_id'=>$product_id,'type'=>$type];
       return $this->queueService->push($data);
    }

    //一般修改或插入
    public function update_insert(array $arr, $arr2)
    {
        $instance = $this->getModelInstance();
        return $instance->updateOrinsert($arr, $arr2);
    }

    /**
     * getData
     * 通过主键id/ids获取信息
     * @param $id id/id数组
     * @param bool $useCache 是否使用模型缓存
     * @return array
     */
    public function find($id, $useCache = true)
    {
        $instance = $this->getModelInstance();

        if ($useCache === true) {
            $modelCache = is_array($id) ? $instance->findManyFromCache($id) : $instance->findFromCache($id);
            return isset($modelCache) && $modelCache ? $modelCache->toArray() : [];
        }
        $query = $instance->query()->find($id);
        return $query->toArray();
    }


    /**
     * 通过主键id/ids获取信息
     * @param $id id/id数组
     * @param array $select
     * @return array
     */
    public function findForSelect($id, $select = ['*'])
    {
        $instance = $this->getModelInstance();

        $query = $instance->query();
        if (is_array($select) && $select[0] != '*') {
            $query->select($select);
        }
        return $query->find($id)->toArray();
    }

    /**
     * 根据条件获取结果
     * @param $where
     * @param bool $type 是否查询多条
     * @param array $select 显示的字段
     * @param string $order 排序方式
     * @return array
     */
    public function getDataByWhereForSelect($where = [], $type = false, $select = ['*'], $order = [])
    {
        $instance = $this->getModelInstance();

        $instance = $this->getWhere($instance, $where);

        if (is_array($select) && $select[0] != '*') {
            $instance->select($select);
        }

        if (!empty($order) && is_array($order)) {
            foreach ($order as $k => $v) {
                $instance->orderBy($k, $v);
            }
        }
        $query = $type ? $instance->get() : $instance->first();
        return empty($query) ? $query : $query->toArray();
    }

    /**
     * 插入并返回id
     * @param array $insertData 插入数据
     * @return int
     */
    public function insertAndGetId($insertData)
    {
        $instance = $this->getModelInstance();
        return $instance->insertGetId($insertData);
    }


    /**
     * deleteByUser
     * 根据ids删除
     * User：YM
     * @param array $ids 删除的主键ids
     * @param int $admin_id 操作人
     * @param int $type 操作类型 1集散地关联 2地标关联 3特产关联  4频道 5售后配置 0不关联
     * @return int
     */
    public function deleteByUser($ids, $admin_id, $type = 0)
    {
        try {
            Db::beginTransaction();
            if ($type != 0) {
                LinkIndustry::query()->where('type', $type)->whereIn('link_id', $ids)->delete();
            }
            $instance = $this->getModelInstance();
            $instance->whereIn('id', $ids)->update(['delete_by' => $admin_id]);
            $instance->whereIn('id', $ids)->delete();
            Db::commit();
            return true;
        } catch (\Throwable $exception) {
            Db::commit();
            return false;
        }
    }

    /**
     * deleteByIds
     * 根据ids删除
     * User：YM
     * @param $ids 删除的主键ids
     * @return int
     */
    public function deleteByIds($ids)
    {
        $instance = $this->getModelInstance();

        return $instance->destroy($ids);
    }

    /**
     * deleteByWhere
     * @param array $where 删除的条件
     * @return mixed
     */
    public function deleteByWhere(array $where = [])
    {
        $instance = $this->getModelInstance();
        $instance = $this->getWhere($instance, $where);
        return $instance->delete();
    }

    /**
     * 获取一列的值
     * @param array $fields
     * @param  $where
     * @return mixed
     */
    public function pluck(array $fields, $where = [])
    {
        $instance = $this->getModelInstance();
        $instance = $this->getWhere($instance, $where);
        return $instance->pluck(implode(',', $fields));
    }


    /**
     * 获取总条数
     * @param array $where
     * @return mixed
     */
    public function count($where = [])
    {
        $instance = $this->getModelInstance();
        $instance = $this->getWhere($instance, $where);
        return $instance->count();
    }


    /**
     * 返回where之后的Instance
     * @param array|\Closure|string $where
     * @param $instance
     * @return mixed
     */
    public function getWhere($instance, $where = [])
    {
        if (is_array($where) && !empty($where)) {
            foreach ($where as $k => $v) {
                if ($v instanceof \Closure) {
                    $instance->where($v);
                } else if (is_array($v)) {
                    if (strtolower($v[0]) == 'in') {
                        $instance->whereIn($k, explode(',', $v[1]));
                    } else {
                        $instance->where($k, $v[0], $v[1]);
                    }
                } else {
                    $instance = $instance->where($k, $v);
                }
                //$instance = is_array($v) ? $instance->where($k, $v[0], $v[1]) : $instance->where($k, $v);
            }
        }
        return $instance;
    }


    /**
     * 插入
     * insert
     * @param array $insertArr
     * @return mixed
     * date:2022/4/26
     * time:17:13
     * auth：xyc
     */
    public function insert(array $insertArr)
    {
        $instance = $this->getModelInstance();
        $instance = $this->setVars($instance, $insertArr);
        if (!($id = $instance->save())) {
            throw new BusinessException(ErrorCode::SERVER_ERROR, get_class($instance) . ": insert faill");
        }
        return $id;
    }


    /**
     * setVars
     * @param $instance
     * date:2022/4/26
     * time:17:09
     * auth：xyc
     * @param array $insertArr
     * @return mixed
     */
    private function setVars($instance, array $insertArr)
    {
        $vars = array_keys(get_object_vars($instance));

        foreach ($insertArr as $var => $value) {
            if (in_array($var, $vars)) {
                $instance->{$var} = $value;
            }
        }
        return $instance;
    }
}